home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d1 / freemacs.arc / TUTORIAL.DOC < prev    next >
Text File  |  1988-03-17  |  26KB  |  746 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.             MINT Tutorial
  13.  
  14. This document assumes that you have loaded it into Tread using the
  15. editor supplied with Tread.  You should read this document and try the
  16. examples that are given.  You may use the arrow keys to view the rest of
  17. the document.
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  
  24.  
  25. Examples
  26.  
  27. You will be asked to execute some of the example programs.  Rather than
  28. force you to type the example in, a MINT program has been written which
  29. executes a MINT program directly from the text.  This MINT program is
  30. appropriately called "try it".  Try it will execute the program that
  31. appears on the line that the cursor is on.  The result of the program,
  32. if any, will be displayed inside quotes on the last line of the screen.
  33.  
  34. To try an example, position the cursor anywhere on the line containing
  35. the example and type the F1 key.  What you have just done is to execute
  36. the try it program.  Don't try to understand exactly how this works yet,
  37. just take for granted that it works.  As The Great Wizard of Oz told
  38. Dorothy, "Pay no attention to the man behind the curtain."
  39.  
  40.  
  41.  
  42. The Basics
  43.  
  44. The basic organizing principle of MINT is this:  Everything is a string,
  45. and strings are sequences of arbitrary characters.  Therefore, programs
  46. are strings and data are strings (yes, data really is plural).  The
  47. following example is a valid MINT program.  It doesn't do anything, but
  48. it's valid.
  49.  
  50.     This is a valid MINT program.
  51.  
  52. Notice that the result of executing the program is just the program
  53. itself.  This is because MINT didn't find any functions to execute.
  54.  
  55.  
  56. A Single Function
  57.  
  58. Now, for a more useful program, you need to know how MINT recognizes
  59. functions.  A MINT function to add two numbers is given below.  The two
  60. character sequence #( begins the function, ++ is the name of the
  61. function, and 5 and 7 are the arguments to the function, seperated by
  62. commas.  The function adds both its arguments and returns the result as
  63. its value.  Try this program in the same manner as before.  You will find
  64. that execute is suggesting "try it".  If this is what you want to do
  65. (and it is), then just type a return.
  66.  
  67.     The sum of five and seven is #(++,5,7).
  68.  
  69. Notice that the MINT function is replaced by "12".  This is how MINT
  70. evaluates its functions.  When a function is recognized, the function is
  71. executed, and its invocation is replaced by its value.
  72.  
  73.  
  74. Multiple Functions
  75.  
  76.  
  77. Functions may be concatenated.  Try the following example.
  78.  
  79.     #(++,1,1)#(++,2,2)
  80.  
  81. You will discover that the result appears to be, and is, twenty four.
  82. This is because you concatenated the results of #(++,1,1) and #(++,2,2)
  83. to get a two and a four next to each other.  Since MINT deals with strings,
  84. a two and a four becomes twenty four.
  85.  
  86.  
  87. Functions may be nested.  Following the logic of the preceding example,
  88. nested functions are evaluated in the following manner: the function that
  89. is found first is executed first, and its invocation is replaced by its
  90. value.  The next function to be found is executed, and its invocation is
  91. replaced by its value.  Try the following example.
  92.  
  93.     #(**,3,#(++,5,7))
  94.  
  95. Notice that the value is 36, which is three multipled by twelve.
  96.  
  97.  
  98. Recognizing Functions
  99.  
  100. MINT recognizes functions by examining the input string character by
  101. character.  A # followed by a ( is taken to be the beginning of a
  102. function.  A , seperates arguments from each other.  A ) causes a
  103. function to be recognized and evaluated.  Let's try the following examples.
  104.  
  105.     #(an,Hello There)
  106.  
  107. The "an" function causes its first argument to be placed on the bottom
  108. line of the screen.
  109.  
  110.     #(an,Hello There
  111.  
  112. Leaving off the closing paren causes the function to execute improperly.
  113.  
  114.     #an,Hello There
  115.  
  116. Leaving off the opening paren causes the function to execute improperly.
  117.  
  118.     (an,Hello There)
  119.  
  120. Leaving off the sharp has a different, desirable effect.  If the MINT
  121. scanner encounters an open paren, then all the characters to the next
  122. matching close paren are skipped.  This is called protecting a string.
  123.  
  124.     (#(an,Hello There))
  125.  
  126. Notice that the "an" function is not executed.  This happens because
  127. those characters are passed over by the scanner.
  128.  
  129.     (#(**,2,#(++,5,7)))
  130.  
  131. Watch what happens when we leave off a close paren.
  132.  
  133.     (#(**,2,#(++,5,7))
  134.  
  135. We end up with the wrong thing being executed.  Watch what happens with
  136. an extra close paren.
  137.  
  138.     (#(**,2,#(++,5,7))))
  139.  
  140. Now nothing happens.  Protection works only if the parentheses are
  141. balanced!
  142.  
  143.  
  144. There are more details concerning scanning, but we'll leave those for
  145. later.
  146.  
  147.  
  148. Strings
  149.  
  150. Not unexpectedly, MINT lets you save strings under a given name.  There
  151. are no restrictions on what you name a string.  Obviously, there are
  152. certain characters that you should avoid including in a name, namely open
  153. paren, comma, and close paren, and a few others.  Let's try an example.
  154. Let's define a string called "my test" and give it the value "this is a
  155. silly test string".  This is an example of the define string function.
  156.  
  157.     #(ds,my test,this is a silly test string)
  158.  
  159. Wow! You just defined a string!  Big, fat, hairy deal.  Defining a string
  160. is useless until you know how to get it back, which leads us to the next
  161. example.  This is an example of the get string function.
  162.  
  163.     #(gs,my test)
  164.  
  165. You don't always have to get the entire string.  There is a pointer
  166. associated with every string.  The gs function doesn't change it, but
  167. some of the following functions do.  You can get the string one character
  168. at a time, and the pointer is advanced by one.  Try this example several
  169. times.
  170.  
  171.     #(go,my test)
  172.  
  173. Notice that you get the characters of "my test" in sequence, starting at
  174. the beginning.  You might be wondering how to position the pointer back
  175. to the beginning.  Well, the following example restores the string
  176. pointer.
  177.  
  178.     #(rs,my test)
  179.  
  180. Now that you're back at the beginning, you're ready to get several
  181. characters, using the get n characters function.  Following this
  182. example, the string pointer is positioned to the "s" of "is".
  183.  
  184.     #(gn,my test,6)
  185.  
  186. You might be wondering what happens if you try to get more characters
  187. than are left following the string pointer.
  188.  
  189.     #(gn,my test,1000)
  190.  
  191. You get all of them, and no more.  There are no more characters left
  192. following the string pointer.  What happens if you try to get one when
  193. there aren't any to get?
  194.  
  195.     #(go,my test,no more)
  196.     #(gn,my test,1,no more)
  197.  
  198. The second argument of get one and the third argument of get n is
  199. returned if there aren't any characters left to get.
  200.  
  201. Well, you could probably search a string for a given substring using the
  202. above functions, but it would be too much work.  A function is provided
  203. for just that purpose.  The first match function finds the first match of
  204. the given string.  To remind you of the value of "my test", let's
  205. redefine it.
  206.  
  207.     #(ds,my test,Another silly test)
  208.     #(fm,my test,silly)
  209.  
  210. The value of first match is the string up to the found string.  The
  211. string pointer, however, is positioned after the last character of the
  212. found match.  This is a nice property.  Let's use it to get the contents
  213. of "my test" one word at a time by searching for the space between
  214. words.  First, we'll restore the string pointer.
  215.  
  216.     #(rs,my test)
  217.     #(fm,my test, )
  218.     #(fm,my test, )
  219.     #(fm,my test, )
  220.  
  221. Aha! We didn't get the last word of "my test".  Well, of course we didn't
  222. because there isn't any space following the word "test".  We'll use this
  223. as an excuse to explain the great lie.
  224.  
  225.  
  226. The Great Lie
  227.  
  228.  
  229. I've been leading you down the primrose path.  To make things simpler,
  230. I've insisted that there is only one type of function invocation.  There
  231. are really two types of functions, active and neutral.  The function you
  232. have been using all along is the active type of function.  After this
  233. function has been scanned, recognized, and evaluated, its result is
  234. re-scanned.  A neutral function's result is not re-scanned.  An example
  235. is in order.  Let's define a string with a function in it.  Remember that
  236. we have to protect the function to keep it from being executed too soon.
  237.  
  238.     #(ds,my function,(#(an,Hello There)))
  239.  
  240. Let's try to retrieve the string the same way that we did earlier.
  241.  
  242.     #(gs,my function)
  243.  
  244. By watching carefully, you can see "Hello There" announced, to be
  245. replaced by two double quotes.  This happens because "my function" is
  246. re-scanned, and MINT sees the "an" function.  Let's try a neutral
  247. function.  The double sharp means neutral, not active.
  248.  
  249.     ##(gs,my function)
  250.  
  251. Now we're getting somewhere!  What happens if we try a triple sharp?
  252. Maybe something else magical will happen?
  253.  
  254.     ###(gs,my function)
  255.  
  256. Nope, no dice.  The extra sharp is treated as just another character,
  257. just like the period in the next example.
  258.  
  259.     .##(gs,my function)
  260.  
  261.  
  262. Let's go back to the first match example.  What were we doing?  Oh yes,
  263. we were trying to get "my test" one word at a time.  We ran into the
  264. difficulty of not having a blank at the end of "my test".  We couldn't
  265. get the following example to work.
  266.  
  267.     #(fm,my test, )
  268.  
  269. Well, rather than keep you in suspense, I'll give you the solution and
  270. explain it afterward.
  271.  
  272.     #(fm,my test, ,(#(gn,my test,100)))
  273.  
  274. Ahhhh.  Success at last.  But why?  Well, if first match doesn't find
  275. the string, it returns its third argument.  The third argument in the
  276. previous example is the "gn" function, which will get as many as it can,
  277. up to the amount specified.  This gets the last word in "my test".
  278.  
  279. But wait...  What if I hadn't wanted to rescan the result of the first
  280. match?  Wouldn't the result be "#(gn,my test,100)"?  Well, no, it
  281. wouldn't, because first match always rescans the third argument if that
  282. is what it returns.  And the same goes for get one and get n.
  283.  
  284.  
  285. Testing
  286.  
  287. So what good would a language be without testing?  Not much good, so
  288. several types of testing are supplied.  The first, equality, is
  289. demonstrated below.
  290.  
  291.     #(==,string,string,yes,no)
  292.     #(==,strin,string,yes,no)
  293.     #(==,string,strin,yes,no)
  294.  
  295. Get the picture?  Those examples are simple but not so useful.  The
  296. following examples are useful but not so simple.
  297.  
  298.     #(==,string,string,(#(an,yes)),(#(an,no)))
  299.     #(==,strin,string,(#(an,yes)),(#(an,no)))
  300.     #(==,string,strin,(#(an,yes)),(#(an,no)))
  301.  
  302. Now you understand why active functions exist.  Most of your testing
  303. functions will be called actively.  Other testing functions will be
  304. explained later.  You're 75% of the way to writing real programs.
  305.  
  306.  
  307. Programs
  308.  
  309. I can see that you're just itching to write your first program.  So be
  310. it.  A program is simply a string that is re-scanned.  Let's write a
  311. really trivial program.
  312.  
  313.     #(ds,trivial,(#(==,a,b,yes,no)))
  314.     #(gs,trivial)
  315.  
  316. Oh boy! This is getting exciting!  The get string function brought
  317. trivial in, rescanned it, found the equality, evaluated it, and returned
  318. "no".  But before you get too pleased with yourself, check out the next
  319. example.
  320.  
  321.     #(trivial)
  322.  
  323. Confusion!  Where is the function name?  Well, there is no function name,
  324. and MINT recognizes that fact.  Rather than throw up its hands in disgust,
  325. MINT assumes that you want to execute "trivial" as a program, and
  326. essentially performs a get string function on "trivial".  Yes, there are
  327. some minor differences, but they will be explained in the next section.
  328.  
  329. Now that you know how to write programs, you'll want to pass parameters
  330. to them.
  331.  
  332.  
  333. Parameters
  334.  
  335. Programs need parameters to be at all useful.  So let's write a non
  336. trivial program, and give it parameters using the make parameter
  337. function.  The second argument to make parameter is purposefully null.
  338. Its meaning will be explained later.
  339.  
  340.     #(ds,non trivial,(#(==,a,b,yes,no)))
  341.     #(mp,non trivial,,a,b)
  342.     #(non trivial,silly,test)
  343.     #(non trivial,test,test)
  344.  
  345. The action of make parameter is to search the specified string for each
  346. of make parameter's arguments, one at a time.  Wherever a match is found,
  347. the string is removed and changed into a parameter.  The third argument
  348. becomes the first parameter, the fourth argument becomes the second
  349. parameter, etc.
  350.  
  351. The mysterious second parameter becomes the "zeroth" parameter.  When a
  352. non-function call is found, such as the "non trivial" example above, the
  353. name of the string is substituted for the "zeroth" parameter.  The use of
  354. this is explained later in the section on looping.
  355.  
  356. Rather than use single characters, such as "a" and "b" used previously,
  357. we shall use arg1, arg2, arg3, etc.  This helps arguments to stand out
  358. from the surrounding text.
  359.  
  360. The "non trivial" program returns yes if its two parameters are equal,
  361. and no otherwise.  Returning yes or no can be useful, but let's do
  362. something even more useful - return a function.  Remember that we have to
  363. protect the parameters arg2 and arg3, otherwise they both will be evaluated
  364. before the equality function is evaluated.  We also have to protect the
  365. functions that we are passing as parameters to null, otherwise they will
  366. get evaluated too soon.
  367.  
  368.     #(ds,null,(#(==,arg1,,(arg2),(arg3))))
  369.     #(mp,null,,arg1,arg2,arg3)
  370.     #(null,a,(#(an,Yes)),(#(an,No)))
  371.     #(null,,(#(an,Yes)),(#(an,No)))
  372.  
  373.  
  374.  
  375. Looping
  376.  
  377. MINT doesn't have while loops, or repeat until loops, or for next loops,
  378. although you could write any of them if you wish.  MINT has something
  379. which is better, called recursion.  Observe the following program, but
  380. don't try it yet!
  381.  
  382.     #(ds,recurse,(#(an,arg1)#(recurse,#(++,arg1,1))))
  383.     #(mp,recurse,,arg1)
  384.     #(recurse,1)
  385.  
  386. Notice that the program announces its parameter, and then calls itself
  387. (recurses) with one more than its argument.  There's no provision for
  388. stopping! Fortunately, MINT allows you to break out of any running
  389. program with the break key (Z-100 uses Shift-Help, IBM-PC uses
  390. Ctrl-Prtsc).  Ok, try the program.  When you get bored, use the break key
  391. to abort the program.
  392.  
  393. Clearly, we need to exercise more control over looping.  Let's rewrite
  394. "recurse" so that it stops at 100.
  395.  
  396.     #(ds,recurse,(#(an,arg1)#(==,arg1,100,,(#(recurse,#(++,arg1,1))))))
  397.     #(mp,recurse,,arg1)
  398.     #(recurse,1)
  399.  
  400. Recurse announces it argument, and checks for equality with 100.  The
  401. value of the equality is null if we've gotten to 100, otherwise it's a
  402. recursive call to itself with one more than itself.
  403.  
  404. Let's get really tricky and use the "zeroth parameter" referred to in the
  405. previous section on parameters.  Notice that we are now using the second
  406. argument to make parameter.
  407.  
  408.     #(ds,recurse,(#(an,arg1)#(==,arg1,100,,(#(SELF,#(++,arg1,1))))))
  409.     #(mp,recurse,SELF,arg1)
  410.     #(recurse,1)
  411.  
  412. When recurse is called, the SELF parameter is replaced by "recurse",
  413. so we are effectively doing the same thing as before.  By using SELF, we
  414. make it obvious that recurse is recursing, and we avoid having to
  415. explicitly name it within itself.  The advantage of this becomes apparent
  416. when you try to change the name of a function.  The fewer places that the
  417. name appears, the easier it is to change.
  418.  
  419.  
  420. Math
  421.  
  422. Math in MINT is performed on strings of digits.  A number in MINT is
  423. considered to be all the digits at the end of a string.  Try the
  424. following example.
  425.  
  426.     #(++,Boeing 707,Lockheed 40)
  427.  
  428. You can see that the two numbers are added and their sum  placed at the
  429. end of the first argument.  The other four math operations  work the same
  430. way.  The only function whose meaning is not obvious is "%%", which means
  431. modulo.
  432.  
  433.  
  434.     #(--,Boeing 707,Lockheed 40)
  435.     #(**,Boeing 707,Lockheed 40)
  436.     #(//,Boeing 707,Lockheed 40)
  437.     #(%%,Boeing 707,Lockheed 40)
  438.  
  439. Numeric tests are performed using the greater than function.
  440.  
  441.     #(g?,10,20,yes,no)
  442.     #(g?,10,10,yes,no)
  443.     #(g?,20,10,yes,no)
  444.  
  445. Numeric conversions from one base to another are possible.  The following
  446. examples convert 64 decimal to other bases.
  447.  
  448.     64 decimal is #(bc,64,d,a) ASCII
  449.     64 decimal is #(bc,64,d,h) hex
  450.     64 decimal is #(bc,64,d,o) octal
  451.     64 decimal is #(bc,64,d,b) binary
  452.  
  453. The same rules for decimal numbers apply to non-decimal numbers.
  454. Converting from one base to the same base is a simple way to remove the
  455. non-digit prefix string.
  456.  
  457.     #(bc,43210,b,b)
  458.     #(bc,a9876,o,o)
  459.     #(bc,cba98,d,d)
  460.     #(bc,ihgfe,h,h)
  461.  
  462.  
  463. Base conversion provides a simple way to include a left or right paren in
  464. a program.
  465.  
  466.     ##(bc,40,d,a)
  467.     ##(bc,41,d,a)
  468.  
  469.  
  470. Odds and Ends
  471.  
  472. There are a few more functions to cover, most of which are interesting but
  473. not important enough to warrant their own section.
  474.  
  475. The output string function outputs its argument to the screen.  This is
  476. useful for sending escape sequences to the screen, and ringing the bell.
  477. Under no circumstances should it be used to send messages to the user.
  478. That is reserved for announce.
  479.  
  480.     #(os,)
  481.  
  482. The halt function unconditionally exits the MINT interpreter.  Usually
  483. you want to make sure that the editor, text buffers, etc are saved before
  484. you execute this function.
  485.  
  486.     #(hl -- you don't really want to try this)
  487.  
  488. The number of characters function counts the number of characters in its
  489. first argument.
  490.  
  491.     #(nc,abcd)
  492.  
  493. Several functions exist strictly for the use of debugging Tread itself.
  494. They are only mentioned so that they may be avoided.
  495.  
  496.     #(db -- you don't really want to try this)
  497.     #(ts -- you don't really want to try this)
  498.     #(tt -- you don't really want to try this)
  499.  
  500. Date and time return the date and time.  Ho hum.
  501.  
  502.     #(dt)
  503.     #(tm)
  504.  
  505. There are several functions pertaining to strings.  The list strings
  506. function returns a list of the names of the strings that have already
  507. been defined.  Each name is followed by a copy of the second argument.
  508. Only those names that begin with the third argument are listed.  You
  509. may be surprised by the number of names listed.  Remember that the editor
  510. that you are using right now is written in MINT.
  511.  
  512.     #(ls,/)
  513.     #(ls,/,r)
  514.  
  515. Suppose we wanted to see if a string existed.  We could get the string
  516. and see if what we got wasn't null, but that fails for strings that exist
  517. and are null.  Well, the name test function comes to our rescue.
  518.  
  519.     #(n?,some silly name that doesn't exist,yes,no)
  520.     #(n?,recurse,yes,no)
  521.  
  522. The second example works because we defined recurse earlier.
  523.  
  524. Just as strings may be defined, they may be erased using erase string.
  525. Erase string may have any number of arguments.
  526.  
  527.     #(ds,foobar,this is foobar)
  528.     #(n?,foobar,y,n)
  529.     #(es,foobar)
  530.     #(n?,foobar,y,n)
  531.  
  532. Just for grins, puzzle out what the following example would do.
  533.  
  534.     #(es -- don't do it,#(ls,(,)))
  535.  
  536. Strings may be saved to and loaded from disk using save library and load
  537. library.  Remember the recurse program we wrote long ago?  Let's save it
  538. and my test into a temporary file.  Save library may have any number of
  539. arguments.
  540.  
  541.     #(sl,mine.tmp,recurse,my test)
  542.  
  543. If we ever want to load them back, we would use load library.  All the
  544. strings stored in the file are loaded.
  545.  
  546.     #(ll,mine.tmp)
  547.  
  548. Strings may be compared for alphabetic ordering.
  549.  
  550.     #(a?,abcd,abce,yes,no)
  551.     #(a?,abcd,abcde,yes,no)
  552.     #(a?,abce,abcd,yes,no)
  553.     #(a?,abcde,abcd,yes,no)
  554.     #(a?,abcd,abcd,yes,no)
  555.  
  556. A single character may be input using input character.  Try the following
  557. example and press any  character.
  558.  
  559.     #(ic)
  560.  
  561. You may also wish to wait a specified time for a character to appear.
  562. The next example will wait for five seconds for a key to be pressed.  If
  563. a key was pressed, then the key will be input.  The check key function
  564. returns a null value if no key was pressed in the specified number of
  565. hundreths of a second.  If a key was pressed, the key will be returned
  566. but not input.  The next input character function will input the key.
  567.  
  568.     #(==,##(ck,500),,no key pressed,(##(ic)))
  569.  
  570.  
  571. Text Buffer
  572.  
  573. The following functions deal with the text buffer.
  574.  
  575. There is a dual representation of text in the text buffer.  One is in
  576. memory, and the other is on the screen.  The function which updates this
  577. mapping is called redisplay.  You may try the following example if you
  578. wish, but since you are using Tread to view this text buffer, the screen
  579. already matches the memory.
  580.  
  581.     #(rd)
  582.  
  583. Redisplay has other functions.  If the first parameter is not null, then
  584. the current contents of the screen are thrown away, and the screen is
  585. entirely repainted.  The second parameter gives the desired cursor
  586. position.  The next examples move the cursor to the top, middle and
  587. bottom of the screen respectively.
  588.  
  589.     #(rd,,1)
  590.     #(rd,,12)
  591.     #(rd,,24)
  592.  
  593.  
  594. There are only three functions which change the text in the buffer.  One
  595. of them is the read file function, which will be discussed later.
  596. Another is the insert string function.  Watch what happens when the next
  597. example is executed.
  598.  
  599.     #(is,Hi!)
  600.  
  601. The string "Hi!" should get inserted at the beginning of the example line.
  602.  
  603. Yet another function to modify the buffer is the delete to mark function.
  604. But before we can try it, we need to introduce marks.
  605.  
  606. Marks
  607.  
  608. To solve the problem of moving around in the buffer, the concept of the
  609. mark was created.  Do not confuse a MINT mark with a Tread mark.  The
  610. Tread marks are defined in terms of MINT marks.  A mark is a single ASCII
  611. character.  There are two types of marks - system (predefined) and
  612. user (variable).  The system marks are given below, and the user marks
  613. are discussed later.
  614.  
  615.     .        The point.
  616.     <        The character to the left of the point.
  617.     >        The character to the right of the point.
  618.     {        The word to the left of the mark.
  619.     }        The word to the right of the mark.
  620.     ^        The beginning of this line.
  621.     $        The end of this line.
  622.     *        The character selected by the pick device.
  623.     [        The beginning of the file.
  624.     ]        The end of the file.
  625.  
  626. Now let's try an example.  Position the cursor to the beginning of the
  627. next example line, and try it several times.
  628.  
  629.     #(sp,>)
  630.  
  631. The cursor moves to the right once each time that you try it.
  632. Position the cursor to the end of the next example line and try it
  633. several times.
  634.  
  635.     #(sp,<)
  636.  
  637. The cursor moves to the left once each time that you try it.  Position
  638. the cursor anywhere in the next example and try it.
  639.  
  640.     #(sp,^)
  641.  
  642. The cursor always moves to the beginning of the line.   Position the
  643. cursor anywhere in the next example and try it.
  644.  
  645.     #(sp,$)
  646.  
  647. The cursor always moves to the end of the line.  We'll skip over the [
  648. and ] marks, since it's tedious to find this spot in the text again.  You
  649. can imagine how they work, however.
  650.  
  651.  
  652. Now that you know how to put text into the buffer, you need to know how
  653. to read it out of the buffer.  The read to mark function will return as
  654. its value the contents of the text buffer between the point and the
  655. specified mark.  Position the cursor to various points on the next
  656. example line and try it.  Notice that the function is a neutral call (Why?).
  657.  
  658.     ##(rm,$)
  659.     ##(rm,^)
  660.     ##(rm,>)
  661.     ##(rm,<)
  662.  
  663. Remember that I deferred talking about deleting text from the buffer? 
  664. Now you'll learn how.  The delete to mark function deletes the contents
  665. of the text buffer between the point and the specified mark.
  666.  
  667.     #(dm,$) position the cursor here >< and delete this.
  668.     delete this >< #(dm,^)
  669.     #(dm,>) position the cursor here >< and delete the left angle.
  670.     #(dm,<) position the cursor here >< and delete the right angle.
  671.  
  672.  
  673. User Marks
  674.  
  675. User marks come in two flavors, local and global.  They are called local
  676. and global because they correspond to the high level language concepts of
  677. the same name.  Global marks are always available, while only the current
  678. set of local marks are available.  A local mark is used for saving the
  679. point while you go off and do something else.  A global mark is used for
  680. saving the point to make it available to other functions.
  681.  
  682. Global marks are allocated by using a negative argument to the pm function.
  683. This also destroys all local marks.  We won't try an example right now,
  684. since the example would cause Tread to barf.
  685.  
  686.     @ through Z    Global user marks.
  687.     0 through 9    Local user marks.
  688.  
  689. User marks may be set using the set mark function.  The following example
  690. sets the global mark @ to the beginning of the file.
  691.  
  692.     #(sm,@,[)
  693.  
  694. The next example sets the same mark to the point.  If the second argument
  695. is missing, it defaults to the point.
  696.  
  697.     #(sm,@)
  698.  
  699. Earlier I referred to "words".  There are two types of characters - "word"
  700. characters and non-"word" characters.  Rather than hard code a character type
  701. into a program, a table is used.  This table is simply a string that is 256
  702. characters long.  The "word" bit is bit zero, so that if the 33 character of
  703. the syntax table string (which is "!") has an odd value, then "!" is considered
  704. to be a word character.  This would be unusual.  A more usual example would
  705. cause "_" to be a word character.  The following example sets the string
  706. "Fsyntax" to be the syntax table.
  707.  
  708.     #(st,Fsyntax)
  709.  
  710.  
  711.  
  712.     "lp" - look pattern
  713.     "lk" - look
  714.  
  715.  
  716.  
  717. Files
  718.  
  719. You can write a file from a buffer using the wf primitive.  All the text
  720. between the point and the mark that you specify will be written to the named
  721. file.  Position the cursor to the beginning of the example line and try it.
  722. The example will write a one line file containing itself.
  723.  
  724.     #(wf,test.tmp,$)
  725.  
  726. You can read a file into a buffer using the rf primitive.  If the result of rf
  727. is null, the file was read in successfully, otherwise the result of rf is a
  728. readable error message.  Read in the file that was written in the previous
  729. example:
  730.  
  731.     #(rf,test.tmp)
  732.  
  733. You have access to MS-DOS's directory using the ff primitive.  The following
  734. example will list all the .ED files with a bar between them:
  735.  
  736.     #(ff,*.ed,|)
  737.  
  738. You can rename MS-DOS files using the rn primitive.  Let's rename the test file
  739. that we wrote previously:
  740.  
  741.     #(rn,test.tmp,test.$$$)
  742.  
  743. Let's delete the test file with its new name:
  744.  
  745.     #(de,test.$$$)
  746.